package com.raymond.client.netty;


import com.raymond.client.constants.GlobalConstants;
import com.raymond.client.enums.MsgHead;
import com.raymond.client.msg.BaseAgreement;
import com.raymond.client.remoting.RemotingHelper;
import com.raymond.client.remoting.RemotingUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 协议解码
 *
 * @author :  raymond
 * @version :  V1.0
 * @date :  2021-07-13 11:42
 */
public class AgreementDecoder extends LengthFieldBasedFrameDecoder {
    private final static Logger logger = LoggerFactory.getLogger(AgreementDecoder.class);

    private static final int FRAME_MAX_LENGTH =
            Integer.parseInt(System.getProperty("com.raymond.remoting.frameMaxLength", "16777216"));

    public AgreementDecoder() {
        super(FRAME_MAX_LENGTH , 0, 4, -4, 0, true);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf bytebuf) throws Exception {
        ByteBuf frame = null;
        try {
            frame = (ByteBuf) super.decode(ctx, bytebuf);
            if (null == frame) {
                return null;
            }
            return byte2BaseAgreement(frame);
        } catch (Exception e) {
            logger.error("decode exception, " + RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e);
            RemotingUtil.closeChannel(ctx.channel());
        } finally {
            if (null != frame) {
                frame.release();
            }
        }
        return null;
    }

    protected BaseAgreement byte2BaseAgreement(ByteBuf bytebuf) {
        return byteBuf2BaseAgreement(bytebuf);
    }

    public static BaseAgreement byteBuf2BaseAgreement(ByteBuf bytebuf) {
        BaseAgreement baseAgreement = new BaseAgreement();
        baseAgreement.setTotalLength(bytebuf.readInt());
        baseAgreement.setCommandId(bytebuf.readInt());
        baseAgreement.setSequenceId(bytebuf.readInt());
        baseAgreement.setHeadLength(MsgHead.getHeadLength());
        baseAgreement.setBodyLength(baseAgreement.getTotalLength() - baseAgreement.getHeadLength());
        if (baseAgreement.getBodyLength() > 0) {
            baseAgreement.setBodyBuffer(new byte[baseAgreement.getBodyLength()]);
            assert(baseAgreement.getBodyLength() == bytebuf.readableBytes());
            bytebuf.readBytes(baseAgreement.getBodyBuffer());
        } else {
            baseAgreement.setBodyBuffer(GlobalConstants.EMPTY_BYTES);
        }
        return baseAgreement;
    }

}
